package com.zxtech.zzm.zxmonitorsocket.resolver

import android.util.Log
import com.zxtech.zzm.core.util.CodecUtil
import com.zxtech.zzm.core.util.DeviceUtil
import com.zxtech.zzm.core.util.HexUtil
import com.zxtech.zzm.ftp.FTPUploadThread
import com.zxtech.zzm.ftp.LogUploadTask
import com.zxtech.zzm.ftp.`interface`.FTPUploadStatusInterface
import com.zxtech.zzm.zxmonitorsocket.SocketPackage
import com.zxtech.zzm.zxmonitorsocket.SocketPackageSend
import com.zxtech.zzm.zxmonitorsocket.ZXMonitorSocketService
import com.zxtech.zzm.zxmonitorsocket.thread.ThreadPoolManager
import com.zxtech.zzm.zxmonitorsocket.util.SocketLoggerUtil
import java.io.File
import java.io.UnsupportedEncodingException
import java.nio.charset.Charset
import java.util.LinkedList
import java.util.Queue

class LogUploadResolver : SocketBaseResolver(), FTPUploadStatusInterface {
  /*private val executor = ThreadPoolExecutor(
      2,  //当某个核心任务执行完毕，会依次从缓冲队列中取出等待任务
      5,  //5,先corePoolSize,然后new LinkedBlockingQueue<Runnable>(),然后maximumPoolSize,但是它的数量是包含了corePoolSize的
      60,  //表示的是maximumPoolSize当中等待任务的存活时间
      SECONDS, LinkedBlockingQueue(),  //缓冲队列，用于存放等待任务，Linked的先进先出
      Executors.defaultThreadFactory(),  //创建线程的工厂
      AbortPolicy() //用来对超出maximumPoolSize的任务的处理策略
  )*/

  override fun resolve(content: Any) {
    FTPUploadThread.instance.statusInterface = this
    val socketPackage = content as SocketPackage
    SocketLoggerUtil.logSocket("LogUploadResolver")
    val userUUID: String = socketPackage.packageContent!!.substring(2, 34)
    SocketLoggerUtil.logSocket("userUUID = $userUUID")
    val taskUUID: String = socketPackage.packageContent!!.substring(34, 98)
    SocketLoggerUtil.logSocket("taskUUID = $taskUUID")
    var uploadInfo: String? = null
    try {
      uploadInfo = String(
        HexUtil.decodeHex(
          socketPackage.packageContent!!.substring(98)
            .toCharArray()
        ), Charset.forName("UTF-8")
      )
    } catch (e: UnsupportedEncodingException) {
      e.printStackTrace()
    }
    SocketLoggerUtil.logSocket("uploadInfo = $uploadInfo")
    if (uploadInfo!!.split("|")
        .toTypedArray().size != 2
    ) {
      replyFail(LogUploadTask(userUUID, taskUUID, "OrderError", ""))
    } else {
      val temp = uploadInfo.split("|")
        .toTypedArray()
      val remoteFolderPath = temp[0]
      val localFilePath = temp[1]
      val localFile = File(localFilePath)
      if (!localFile.exists() || !localFile.isFile) {
        replyFail(LogUploadTask(userUUID, taskUUID, "", "localFileNotFound"))
        return
      }
      val task = LogUploadTask(userUUID, taskUUID, remoteFolderPath, localFilePath)
      if (!isExistInList(task)) {
        logUploadTasks.offer(task)
        val ftpUploadThread: FTPUploadThread = FTPUploadThread.instance
        //executor.execute(ftpUploadThread)
        ThreadPoolManager.instance?.execute(ftpUploadThread)
      } else {
        replyFail(LogUploadTask(userUUID, taskUUID, "", "alreadyInTaskList"))
      }
    }
  }

  /**
   * 判断列表内是否有相同的任务，避免重复上传
   */
  private fun isExistInList(task: LogUploadTask): Boolean {
    for (temptask in logUploadTasks) {
      if (temptask.localFilePath == task.localFilePath
        && temptask.remoteFolderPath == task.remoteFolderPath
      ) {
        return true
      }
    }
    return false
  }

  companion object {
    val instance = LogUploadResolver()
    private val logUploadTasks: Queue<LogUploadTask> = LinkedList()
    fun getLogUploadTasks(): Queue<LogUploadTask> {
      return logUploadTasks
    }

    fun handlePackage(socketPackage: SocketPackage?) {
      instance.resolve(socketPackage!!)
    }
  }

  override fun replyUploading(
    task: LogUploadTask,
    uploadSize: Long
  ) {
    Log.e("zzm debug", "replyUploading $uploadSize")
    val localSize: Long = File(task.localFilePath).length()
    val progress = "$localSize|$uploadSize"
    val lengthByte: ByteArray = CodecUtil.short2bytes(
      (50 + progress.toByteArray().size).toShort()
    )
    val data_success = ByteArray(50 + progress.toByteArray().size)
    data_success[0] = 0x02
    val userUUIDbytes: ByteArray = CodecUtil.hexStringToByte(task.userUUID)
    System.arraycopy(userUUIDbytes, 0, data_success, 1, userUUIDbytes.size)
    val taskUUIDbytes: ByteArray = CodecUtil.hexStringToByte(task.taskUUID)
    System.arraycopy(taskUUIDbytes, 0, data_success, 17, taskUUIDbytes.size)
    data_success[49] = 0x00 //上传中
    val progressBytes = progress.toByteArray()
    System.arraycopy(progressBytes, 0, data_success, 50, progressBytes.size)
    val builder = SocketPackageSend.Builder()
    builder.setPackageLength(byteArrayOf(lengthByte[0], lengthByte[1]))
      .setType(0x23.toByte())
      .setIdBytes(
        DeviceUtil.getTerminalID()
          .toByteArray()
      )
      .setData(data_success)
    ZXMonitorSocketService.sendPackage(builder)
  }

  override fun replySuccess(task: LogUploadTask) {
    Log.e("zzm debug", "replySuccess")
    val localSize: Long = File(task.localFilePath).length()
    val progress = "$localSize\\|$localSize"
    val lengthByte: ByteArray = CodecUtil.short2bytes(
      (50 + progress.toByteArray().size).toShort()
    )
    val data_success = ByteArray(50 + progress.toByteArray().size)
    data_success[0] = 0x02
    val userUUIDbytes: ByteArray = CodecUtil.hexStringToByte(task.userUUID)
    System.arraycopy(userUUIDbytes, 0, data_success, 1, userUUIDbytes.size)
    val taskUUIDbytes: ByteArray = CodecUtil.hexStringToByte(task.taskUUID)
    System.arraycopy(taskUUIDbytes, 0, data_success, 17, taskUUIDbytes.size)
    data_success[49] = 0x01 //成功
    val progressBytes = progress.toByteArray()
    System.arraycopy(progressBytes, 0, data_success, 50, progressBytes.size)
    val builder = SocketPackageSend.Builder()
    builder.setPackageLength(byteArrayOf(lengthByte[0], lengthByte[1]))
      .setType(0x23.toByte())
      .setIdBytes(
        DeviceUtil.getTerminalID()
          .toByteArray()
      )
      .setData(data_success)
    ZXMonitorSocketService.sendPackage(builder)
  }

  override fun replyFail(task: LogUploadTask) {
    Log.e("zzm debug", "replyFail:$task")
    val lengthByte: ByteArray = CodecUtil.short2bytes(50.toShort())
    val data_fail = ByteArray(50)
    data_fail[0] = 0x02
    val userUUIDbytes: ByteArray = CodecUtil.hexStringToByte(task.userUUID)
    System.arraycopy(userUUIDbytes, 0, data_fail, 1, userUUIDbytes.size)
    val taskUUIDbytes: ByteArray = CodecUtil.hexStringToByte(task.taskUUID)
    System.arraycopy(taskUUIDbytes, 0, data_fail, 17, taskUUIDbytes.size)
    data_fail[49] = 0x02 //失败
    val builder = SocketPackageSend.Builder()
    builder.setPackageLength(byteArrayOf(lengthByte[0], lengthByte[1]))
      .setType(0x23.toByte())
      .setIdBytes(
        DeviceUtil.getTerminalID()
          .toByteArray()
      )
      .setData(data_fail)
    ZXMonitorSocketService.sendPackage(builder)
  }

  override fun getLogUploadTasks(): Queue<LogUploadTask> {
    return logUploadTasks
  }
}